package thingapi

import (
	"iot-base/common/cache"
	"iot-base/common/crudextend"
	"iot-base/common/dbconn"
	"iot-base/common/dbobj"
	"iot-base/common/idsync"
	"iot-base/common/logger"
	"iot-base/common/webapi"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"gorm.io/gorm"
)

type param struct {
	ParamID    string `json:"param_id"`
	ParamValue string `json:"param_value"`
}

type thingParams struct {
	ThingID string  `json:"thing_id"`
	Values  []param `json:"values"`
}

func updateThingParamRest(c *gin.Context) bool {
	var param thingParams
	c.ShouldBindBodyWith(&param, binding.JSON)
	pInfo, _ := cache.GetThing(param.ThingID)
	if pInfo == nil {
		logger.SLog.Error("thing info not found", param.ThingID)
		return true
	}
	params := make([]dbobj.ThingParam, 0, len(param.Values))
	for _, v := range param.Values {
		var tparam dbobj.ThingParam
		tparam.ThingID = param.ThingID
		tparam.ParamID = v.ParamID
		tparam.ParamValue = v.ParamValue
		tparam.UID = 0
		params = append(params, tparam)

	}
	msg := crudextend.CrudMsg{
		Action:       c.Request.Method,
		TModelID:     pInfo.Thing.ModelID,
		PThing:       &pInfo.Thing,
		PThingParams: &params,
	}
	result := crudextend.GetExtendResult(pInfo.Thing.ModelID, &msg)
	if result != nil && result.Err != nil {
		webapi.SendError(result.Err.Error(), webapi.DBError, c)
		return true
	}
	if result != nil && result.PThingParams != nil {
		params = *result.PThingParams
	}

	err := updateThingParam(param.ThingID, params)
	if err == nil {

		if err != nil {

			webapi.SendError("update param "+err.Error(), webapi.DBError, c)
		} else {
			webapi.SendResult(&param, nil, c)
		}

	} else {
		webapi.SendError("update param "+err.Error(), webapi.DBError, c)
	}
	return true
}
func updateThingParam(thid string, params []dbobj.ThingParam) error {
	errDB := dbconn.DBConnection.Transaction(func(tx *gorm.DB) error {
		err := tx.Debug().Delete(dbobj.ThingParam{}, "thing_id=?",
			thid).Error
		if err == nil {
			if len(params) > 0 {
				for _, v := range params {
					err = tx.Create(&v).Error
					if err != nil {
						return nil
					}
				}
			}
		} else {
			return err
		}

		// 返回 nil 提交事务
		return nil
	})
	if errDB == nil {
		idsync.DirtyThing(thid)
	}
	return errDB
}

func addParam(id, defaultValue, tid string, pResult *[]dbobj.ThingParam) {
	isIn := false
	for _, param := range *pResult {
		if param.ParamID == id {
			isIn = true
			break
		}
	}
	if !isIn {
		param := dbobj.ThingParam{
			ParamID:    id,
			ParamValue: defaultValue,
			//SName:      name,
			ThingID: tid,
		}
		*pResult = append(*pResult, param)
	}
}

func queryThingParamRest(c *gin.Context) bool {
	tid := c.Param("id")
	var result []dbobj.ThingParam
	err := dbconn.DBConnection.Model(&dbobj.ThingParam{}).Where("thing_id=?",
		tid).Find(&result).Error
	if err != nil {
		webapi.SendError("update param "+err.Error(), webapi.DBError, c)
	} else {
		addParam("interval", "10", tid, &result)
		//addParam("spec", "", tid, &result)
		webapi.SendResult(result, nil, c)
	}

	return true
}

func deleteThingParamRest(c *gin.Context) bool {
	tid := c.Param("id")
	var result []dbobj.ThingParam
	err := dbconn.DBConnection.Exec("delete from thing_params where thing_id=?", tid).Error
	if err != nil {
		webapi.SendError("update param "+err.Error(), webapi.DBError, c)
	} else {
		idsync.DirtyThing(tid)
		webapi.SendResult(result, nil, c)
	}

	return true
}
